/*
 * @file    :task_comm.c
 * @module  :COMM TASK
 * @author  :LingFengLu
 * @date    :2023-06-08
 */

#include "task_comm.h"
#include "task.h"
#include "mid.h"
#include "drv.h"
#include "lib_string.h"
#include "lib_queue.h"
#include "lib_checksum.h"
#include "message.h"
#include "devos.h"
#include "devcomm.h"
#include "task_glucose.h"
//Constant definition    宏定义
#define TASK_COMM_ENCRYPTION               		1
#define TASK_COMM_ENCRYPTION_UPDATE         	1
#define TASK_COMM_SET_AUTHORITY					1

#define TASK_COMM_ADDRESS_LENGTH            	6
#define TASK_COMM_USER_ID_LENGTH            	32
#define TRANS_RATE_DEFAULT0                 	2
#define TRANS_RATE_DEFAULT1                 	1

#define ROLE_PRIMARY                        	1
#define ROLE_SECONDARY                      	0

#define TASK_COMM_PACKET_LENGTH_MAX			   	128
#define TASK_COMM_PACKET_LENGTH_MASTER		   	19
#define TASK_COMM_PACKET_LENGTH_SLAVE		   	32
#define TASK_COMM_SEND_RETRY				   	3
#define TASK_COMM_SEND_TIMEOUT				   	500
#define RECEIVE_BUFFER_SIZE                    	(BLE_MTU - BLE_GATT_ATT_OP_LEN - BLE_GATT_ATT_HANDLE_LEN)*2
#define LENGTH_BUFFER_SIZE			           	6
#define DATA_WRITE_BUFFER_SIZE                 	128
#define DATA_READ_BUFFER_SIZE                  	42
#define TASK_COMM_BUFFER_SIZE_MESSAGE          	160
#define TASK_COMM_BUFFER_SIZE_DEVICE_EVENT     	16
#define TASK_COMM_BUFFER_SIZE_COMMAND          	140

#define WRITE_DELAY_RATIO	1
//Type definition    类型定义
typedef enum
{
	COMM_OPERATION_WRITE = 0,
	COMM_OPERATION_READ,
	COMM_COUNT_OPERATION
} comm_operation;

typedef struct
{
	uint8* u8_BufferData;
	uint8 u8_BufferLength[LENGTH_BUFFER_SIZE];
	lib_queue_object t_QueueData;
	lib_queue_object t_QueueLength;
} comm_control;

typedef struct
{
	uint8 u8_Address;
	uint8 u8_SourcePort;
	uint8 u8_TargetPort;
	uint8 u8_Mode;
	uint8 u8_Length;
} task_comm_message;

typedef enum
{
	TASK_COMM_DEVICE_RF= 0,
	TASK_COMM_COUNT_DEVICE
} task_comm_device;

typedef enum
{
	TASK_COMM_FLAG_SWITCH = 0,
	TASK_COMM_FLAG_BROADCAST_PENDING,
	TASK_COMM_FLAG_INFO_UPDATING,
	TASK_COMM_FLAG_BONDED,
	TASK_COMM_FLAG_PRIMARY,
	TASK_COMM_COUNT_FLAG
} task_comm_flag;

typedef enum
{
	TASK_COMM_EVENT_WRITE_DONE = 0,
	TASK_COMM_EVENT_READ_DONE,
	// TASK_COMM_EVENT_STATE_CHANGE,
	// TASK_COMM_EVENT_DELAY_WRITE_DONE_BROADCAST,
	// TASK_COMM_EVENT_DELAY_WRITE_DONE_CONNECTION,
	// TASK_COMM_EVENT_DELAY_SCAN,
	// TASK_COMM_EVENT_DELAY_CONNECTION,
	// TASK_COMM_EVENT_MANAGEMENT,
	TASK_COMM_COUNT_EVENT
} task_comm_event;

//Global variable definition    全局变量定义


//Private variable definition    私有变量定义
static const uint8 m_u8_Reboot[16] ={ 'f', 'o', 'r', 'c', 'e', ' ', 'r', 'e', 'b', 'o', 'o', 't', ' ', 'a', 'l', 'l' };
static const uint8 m_u8_RebootAsc[16] ={ 'f', 'o', 'r', 'c', 'e', ' ', 'r', 'e', 'b', 'o', 'o', 't', ' ', 'g', 'c' };
static const uint8 m_u8_ClearPairingInfo[16] ={ 'f', 'o', 'r', 'c', 'e', ' ', 'u', 'n', 'p', 'a', 'i', 'r', ' ', 'a', 'l', 'l' };
static const uint8 m_u8_GetLogNum[14] ={ 'g', 'e', 't', ' ', 'l', 'o', 'g', ' ', 'n', 'u', 'm', 'b', 'e', 'r' };
static const uint8 m_u8_Log[3] ={ 'l', 'o', 'g' };
static const uint8 m_u8_GetR[4] = { 'g', 'e', 't','r' };
static const uint8 m_u8_CalR[4] =  { 'c', 'a', 'l','r'  };
static const uint8 m_u8_GetPairInfo1[15] = { 'g', 'e', 't',' ','p','a','i','r',' ','i','n','f','o',' ','0' };
static const uint8 m_u8_GetPairInfo2[15] = { 'g', 'e', 't',' ','p','a','i','r',' ','i','n','f','o',' ','1' };
static uint m_ui_Flag[MESSAGE_COUNT_ADDRESS] = {0};
static uint m_ui_MessageID = 0;
static uint8 m_u8_BufferCommand[TASK_COMM_BUFFER_SIZE_COMMAND] = {0};
static uint8 m_u8_ReceiveBuff[RECEIVE_BUFFER_SIZE]={0};
static uint8 m_u8_ReceiveBuffBak[RECEIVE_BUFFER_SIZE] = {0};
static uint8 m_u8_BufferMessage[MESSAGE_COUNT_ADDRESS][TASK_COMM_BUFFER_SIZE_MESSAGE] = {0};
static const  uint8 m_u8_BufferMessageLength[MESSAGE_COUNT_ADDRESS] = {TASK_COMM_BUFFER_SIZE_MESSAGE, TASK_COMM_BUFFER_SIZE_MESSAGE};
static uint8 m_u8_BufferDeviceEvent[TASK_COMM_BUFFER_SIZE_DEVICE_EVENT];
static lib_queue_object m_t_QueueMessage[MESSAGE_COUNT_ADDRESS] = {0};
static lib_queue_object m_t_QueueDeviceEvent = {0};
static uint m_ui_ReadLength = 0;
static const uint8 *m_u8p_ReadData = {0};
static uint8 m_u8_WriteBufferData[DATA_WRITE_BUFFER_SIZE] = {0};
static uint8 m_u8_ReadBufferData[DATA_READ_BUFFER_SIZE] = {0};
static const uint8 m_u8_BufferSize[COMM_COUNT_OPERATION] = {DATA_WRITE_BUFFER_SIZE,DATA_READ_BUFFER_SIZE};
static uint8 m_u8_TempIv[KEYLEN] = {0};
static const uint8 m_u8_PairingIDLength[TASK_COMM_COUNT_IDENTIFIER] = {TASK_COMM_ADDRESS_LENGTH, TASK_COMM_USER_ID_LENGTH};
static const uint8 m_u8_DefaultTransRate[TASK_COMM_COUNT_IDENTIFIER] = {TRANS_RATE_DEFAULT0, TRANS_RATE_DEFAULT1};
static uint8 m_u8_UpdateKeyFlag =0;
static uint16 m_u16_WriteDelayRatio = WRITE_DELAY_RATIO;
static task_comm_broadcast m_t_Broadcast = {0};
static uint16 m_u16_ConnectWriteDelayRatio = 1;
static uint16 m_u16_ConnectInterval = 0;
static comm_control m_t_CommControl[COMM_COUNT_OPERATION] = 
{
    {
        m_u8_WriteBufferData,{0},{0},{0}
    },
    {
        m_u8_ReadBufferData,{0},{0},{0}
    }
};
static pairing_info m_t_PairingInfo[TASK_COMM_COUNT_IDENTIFIER] =
{
    {
		{0},
        {0},
        {0},
        TASK_COMM_ADDRESS_LENGTH,
        TRANS_RATE_DEFAULT0,
        ROLE_SECONDARY,
        {0}
    },
    {
        
		{0},
        {0},
        {0},
        TASK_COMM_USER_ID_LENGTH,
        TRANS_RATE_DEFAULT1,
        ROLE_SECONDARY,
        {0}
    }
};

//Private function declaration   私有函数申明
static uint TaskComm_InitializeBle(void);
static uint TaskComm_InitializeComm(void);
static uint TaskComm_InitializeOS
( 
    devos_task_handle t_TaskHandle
);
static uint TaskComm_GetDevice
( 
    devcomm_int t_Address,
    devcomm_int *tp_Device 
);

static void TaskComm_Tick
( 
    uint16 u16_TickTime 
);
static void TaskComm_HandleMessage(void);
static uint TaskComm_CheckState
(
	uint8 *u8p_State
);
static uint TaskComm_HandleEvent
( 
    devcomm_int t_Device,
    devcomm_int t_Address,
    devcomm_int t_SourcePort,
    devcomm_int t_TargetPort,
    devcomm_int t_Event
);
static uint TaskComm_WriteDevice
( 
    devcomm_int t_Device,
    const uint8 *u8p_Data,
    devcomm_int t_Length 
);
static uint TaskComm_Write
( 
    const uint8 *u8p_Data,
    uint ui_Length 
);
static uint TaskComm_ReadDevice
( 
    devcomm_int t_Device,
    uint8 *u8p_Data,
    devcomm_int *tp_Length 
);
static uint TaskComm_Read
(
    uint8 *u8p_Data,
    uint *uip_Length 
);

static void TaskComm_Memcpy
( 
    uint8 *u8p_Target, 
    const uint8 *u8p_Source, 
    devcomm_int t_Length 
);

static uint8 TaskComm_GetCRC8
( 
    const uint8 *u8p_Data, 
    devcomm_int t_Length, 
    uint8 u8_Base 
);
static uint16 TaskComm_GetCRC16
( 
    const uint8 *u8p_Data, 
    devcomm_int t_Length, 
    uint16 u16_Base 
);
static void TaskComm_EncryptionUpdate(void);

static void TaskComm_Encrypt
( 
    uint8 *u8p_Data, 
    devcomm_int t_Length 
);
static void TaskComm_Decrypt
( 
    uint8 *u8p_Data, 
    devcomm_int t_Length 
);
static uint TaskComm_SavePairingInfo(void);
static uint TaskComm_SendCommand
( 
    uint8 u8_Address,
    uint8 u8_SourcePort,
    uint8 u8_TargetPort,
    const message_command *tp_Command,
    uint8 u8_Mode 
);
static void TaskComm_BleOnConnect(void);
static void TaskComm_BleOnWrite
(
    uint16 u16_ConnetHandle, 
    uint16 u16_AttIndex, 
    uint8 *u8p_Data, 
    uint16 u16_Len
);

static void TaskComm_CommunicationServicOnWrite
(
    uint8 * u8p_Data, 
    uint16 u16_Length
);
static void TaskComm_ManagementServicOnWrite
(
    uint8 * u8p_Data, 
    uint16 u16_Length
);
static void TaskComm_CommandReceived
(
    uint8 * u8p_Data, 
    uint16 u16_Length
);
void TaskComm_InitFrame
( 
    uint ui_Operation
);
void TaskComm_ResetFrame
( 
    uint ui_Operation
);
static uint TaskComm_AddFrame
( 
    uint ui_Operation,
    const uint8 *u8p_Data,
    uint ui_Length 
);
static uint TaskComm_PopFrame//TaskComm_RemoveFrame
( 
    uint ui_Operation,
    uint8 *u8p_Data,
    uint *uip_Length
);
static uint TaskComm_ProcessFrame
( 
    uint ui_Operation,
    const uint8 *u8p_Data,
    uint ui_Length 
);
static uint TaskComm_Notify
(    
	uint16 u16_AttHandle,  
    const uint8 *u8p_Data, 
    uint ui_Len
);
static void TaskComm_InitDeviceEvent(void);
static void TaskComm_StartWriteTimer
(
	uint16 u16_Interval
);
static void TaskComm_WrtieTimerCallback(void);
static void TaskComm_WriteDone( void );

static uint TaskComm_HandleDeviceRfEvent
( 
    uint ui_Event,
    const uint8 *u8p_Data,
    uint ui_Length 
);
static void TaskComm_UpdateBroadcast(void);
//Public function definition   公共函数定义
void TaskComm_Init
(
	devos_task_handle t_TaskHandle
)
{
	if (TaskComm_InitializeBle() != FUNCTION_OK)
		return ;
	if (TaskComm_InitializeOS(t_TaskHandle) != FUNCTION_OK)
		return ;
	if (TaskComm_InitializeComm() != FUNCTION_OK)
		return ;

}


void TaskComm_Process
(
	devos_task_handle t_TaskHandle
)
{
    static uint8 *u8p_MessageData;
	static devos_int t_MessageLength;
	DEVOS_TASK_BEGIN

	DevOS_MessageWait(DEVOS_MESSAGE_COUNT_MAX, u8p_MessageData, &t_MessageLength);
	TaskComm_HandleMessage();
	DEVOS_TASK_END
}
uint TaskComm_SetConfig
(
	uint ui_Parameter,
	const uint8 *u8p_Value,
	uint ui_Length
)
{
	switch (ui_Parameter)
	{
		case TASK_COMM_PARAM_BROADCAST_DATA:
			Lib_Memcpy((uint8 *)&m_t_Broadcast, u8p_Value, ui_Length);
			TaskComm_UpdateBroadcast();
			break;
		
		default:
			break;
	}
    return FUNCTION_OK;
}
uint TaskComm_GetConfig
(
	uint ui_Parameter,
	uint8 *u8p_Value,
	uint *uip_Length
)
{
	switch (ui_Parameter)
	{
	case TASK_COMM_PARAM_BUSY:

 		if (TaskComm_CheckState(u8p_Value) != FUNCTION_OK)
			return FUNCTION_FAIL;
		break;
	
	default:
		break;
	}
    return FUNCTION_OK;
}


uint TaskComm_Pair
( 
    uint ui_Parameter,
    uint8 *u8p_Value,
    uint *uip_Length 
)
{
	LOG_INFO("TaskComm_Pair");
    pairing_info *tp_PairingInfo;
    uint8 u8_Acknowledge = FUNCTION_FAIL;

    uint8 u8_IdLength = m_t_PairingInfo[ui_Parameter].u8_PairingIDLength;
    if ( ( ui_Parameter == TASK_COMM_IDENTIFIER_ADDRESS ||
           ui_Parameter == TASK_COMM_IDENTIFIER_USER_ID  ) &&
         ( *uip_Length  == u8_IdLength                  ||
           *uip_Length  == u8_IdLength + 1*sizeof(uint8)||
           *uip_Length  == u8_IdLength + 2*sizeof(uint8) ) )
    {
        tp_PairingInfo = &m_t_PairingInfo[ui_Parameter];

        if ( Lib_Memcmpv(tp_PairingInfo->u8_PairingID, 0, tp_PairingInfo->u8_PairingIDLength) == FUNCTION_OK )
        {
            Lib_Memcpy(tp_PairingInfo->u8_PairingID, u8p_Value, tp_PairingInfo->u8_PairingIDLength);
            u8_Acknowledge = FUNCTION_OK;
        }
        else if ( Lib_Memcmp(tp_PairingInfo->u8_PairingID, u8p_Value, tp_PairingInfo->u8_PairingIDLength) == FUNCTION_OK )
        {
            u8_Acknowledge = FUNCTION_OK;
        }
    }

    if (u8_Acknowledge == FUNCTION_OK)
    {
        if ( *uip_Length == u8_IdLength + 1*sizeof(uint8) )
            tp_PairingInfo->u8_TransRate = u8p_Value[*uip_Length-1];
        else if ( *uip_Length == u8_IdLength )
            tp_PairingInfo->u8_TransRate = m_u8_DefaultTransRate[ui_Parameter];
           
		uint32 u32_Rand =1;
		u32_Rand = Drv_Random();
        uint16 u16_Rand = (uint16)u32_Rand;
//////////////////////////////////////////////////////////////////
		if(m_u8_UpdateKeyFlag == 1)
		{

			for (uint i=0; i<TASK_COMM_BOND_ID_LENGTH; i+=2)
			{
				Lib_Memcpy(tp_PairingInfo->u8_BondID+i, (const uint8 *)&u16_Rand, 2);
			}
			for (uint i=0; i<KEYLEN; i+=4)
			{
				u32_Rand = u32_Rand*99991+123457;
				Lib_Memcpy(tp_PairingInfo->u8_Key+i, (const uint8 *)&u32_Rand, 4);
			}
			
	
			for (uint8 i=0; i<TASK_COMM_COUNT_IDENTIFIER; i++)
			{
				if (i == ui_Parameter)
					m_t_PairingInfo[i].u8_Role = ROLE_PRIMARY;
				else
					m_t_PairingInfo[i].u8_Role = ROLE_SECONDARY;
			}
			u8_Acknowledge = TaskComm_SavePairingInfo();
			if(u8_Acknowledge == FUNCTION_FAIL)
			{
				*uip_Length = 1;
				return u8_Acknowledge;
			}
			m_u8_UpdateKeyFlag = 0;
		}

    }

	if(u8_Acknowledge == FUNCTION_FAIL)
	{
		*uip_Length= 1;
		return FUNCTION_FAIL;
	}
		

    if (u8_Acknowledge == FUNCTION_OK && *uip_Length == u8_IdLength + 2*sizeof(uint8))
    {
// 		TaskGlucose_SetConfig(TASK_GLUCOSE_PARAM_HYPO_HYPER,  u8p_Value+u8_IdLength,2*sizeof(uint8));


    }
	    u8p_Value += 1;
        Lib_Memcpy(u8p_Value, tp_PairingInfo->u8_BondID, TASK_COMM_BOND_ID_LENGTH);
        u8p_Value += TASK_COMM_BOND_ID_LENGTH;
        Lib_Memcpy(u8p_Value, tp_PairingInfo->u8_Key, KEYLEN);
	*uip_Length = u8_Acknowledge == FUNCTION_OK? (1 + TASK_COMM_BOND_ID_LENGTH + KEYLEN) : 1;  
    return u8_Acknowledge;
}

uint TaskComm_Unpair
( 
    uint ui_Parameter,
    uint8 *u8p_Value,
    uint *uip_Length 
)
{
    pairing_info *tp_PairingInfo;
    pairing_info t_PairingInfoTemp={0};
    uint8 u8_Acknowledge = FUNCTION_FAIL;

    if (ui_Parameter < TASK_COMM_COUNT_IDENTIFIER)
    {
        tp_PairingInfo = &m_t_PairingInfo[ui_Parameter];
        Lib_Memcpy((uint8 *)&t_PairingInfoTemp,(uint8 *)tp_PairingInfo,sizeof(pairing_info));
        Lib_Memset(tp_PairingInfo->u8_PairingID, 0, tp_PairingInfo->u8_PairingIDLength);
        Lib_Memset(tp_PairingInfo->u8_BondID, 0, TASK_COMM_BOND_ID_LENGTH);
        tp_PairingInfo->u8_Role = ROLE_SECONDARY;
        u8_Acknowledge = TaskComm_SavePairingInfo();

        if(u8_Acknowledge == FUNCTION_FAIL)
        {
            Lib_Memcpy((uint8 *)tp_PairingInfo,(uint8 *)&t_PairingInfoTemp,sizeof(pairing_info));
        }

    }
    *uip_Length = 1;
    return u8_Acknowledge;
}

uint TaskComm_Bond
( 
    uint ui_Parameter,
    uint8 *u8p_Value,
    uint *uip_Length 
)
{
   pairing_info *tp_PairingInfo;
   uint8 u8_Acknowledge = FUNCTION_FAIL;

   if (ui_Parameter < TASK_COMM_COUNT_IDENTIFIER && (*uip_Length == TASK_COMM_BOND_ID_LENGTH || *uip_Length == TASK_COMM_BOND_ID_LENGTH+1))
   {
       tp_PairingInfo = &m_t_PairingInfo[ui_Parameter];
       if ( Lib_Memcmpv( tp_PairingInfo->u8_BondID, 0, TASK_COMM_BOND_ID_LENGTH ) != FUNCTION_OK &&
            Lib_Memcmp( tp_PairingInfo->u8_BondID, u8p_Value,      TASK_COMM_BOND_ID_LENGTH ) == FUNCTION_OK   )
           u8_Acknowledge = FUNCTION_OK;
   }

#if TASK_COMM_ENCRYPTION
#if TASK_COMM_ENCRYPTION_UPDATE
   if (u8_Acknowledge == FUNCTION_OK)
       u8_Acknowledge = DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
                                                  MESSAGE_ADDRESS_MASTER,
                                                  DEVCOMM_ENCRYPTION_UPDATE );
#else
   if (u8_Acknowledge == FUNCTION_OK)
       u8_Acknowledge = DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
                                                  MESSAGE_ADDRESS_MASTER,
                                                  DEVCOMM_ENCRYPTION_ON );
#endif
#endif

   if (u8_Acknowledge == FUNCTION_OK)
   {
       uint8 u8_TransRate;
       if (*uip_Length > TASK_COMM_BOND_ID_LENGTH)
           u8_TransRate = *(u8p_Value+TASK_COMM_BOND_ID_LENGTH);
       else
           u8_TransRate = tp_PairingInfo->u8_TransRate;
       REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_BONDED);
       if (tp_PairingInfo->u8_Role == ROLE_PRIMARY)
       {
           REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_PRIMARY);
       }
       DevComm_Link( TASK_COMM_DEVICE_RF,
                     MESSAGE_ADDRESS_MASTER,
                     19 * u8_TransRate );
       *uip_Length = 1;
#if TASK_COMM_ENCRYPTION
       AES_SetKey(tp_PairingInfo->u8_Key, 0);
#if TASK_COMM_ENCRYPTION_UPDATE
       uint32 u32_Rand =1;
		u32_Rand = Drv_Random();
       for (uint8 i=0; i<KEYLEN; i+=4)
       {
           u32_Rand = u32_Rand*99991+123457;
           Lib_Memcpy(m_u8_TempIv+i, (const uint8 *)&u32_Rand, 4);
       }

		Lib_Memcpy(u8p_Value, m_u8_TempIv, KEYLEN);
       u8p_Value[KEYLEN] = LibChecksum_GetChecksum8Bit(u8p_Value, KEYLEN);
       *uip_Length = KEYLEN + 1;

		if(ui_Parameter == TASK_COMM_IDENTIFIER_ADDRESS)
		{
             m_u16_WriteDelayRatio = WRITE_DELAY_RATIO+1;
		}
		else if(ui_Parameter == TASK_COMM_IDENTIFIER_USER_ID)
		{
            m_u16_WriteDelayRatio = WRITE_DELAY_RATIO;
		}

#endif
#endif
   }
	else
	{
		 *uip_Length = 0;
	}


   return u8_Acknowledge;
}

uint TaskComm_Send
( 
    uint8 u8_Address,
    uint8 u8_SourcePort,
    uint8 u8_TargetPort,
    message_command *tp_Command,
    uint8 u8_Mode 
)
{
  	LOG_INFO("TaskComm_Send-Adr:%d,sp:%d,tp:%d",u8_Address,u8_SourcePort,u8_TargetPort);
	uint ui_Value;
	devcomm_int t_Device;
	devcomm_int t_State;
	task_comm_message t_Message;

	if ( u8_Address >= MESSAGE_COUNT_ADDRESS )
		return FUNCTION_FAIL;

	if ( TaskComm_GetDevice((devcomm_int)u8_Address, &t_Device) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if ( DevComm_Query(t_Device, (devcomm_int)u8_Address, DEVCOMM_INFO_STATE, &t_State) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if (t_State == DEVCOMM_STATE_BUSY)
	{
	    if ( LibQueue_GetConfig( &m_t_QueueMessage[u8_Address],
	                             LIB_QUEUE_PARAM_BUFFER_SPACE,
	                             (void *)&ui_Value ) != FUNCTION_OK )
			return FUNCTION_FAIL;

		t_Message.u8_Address = u8_Address;
		t_Message.u8_SourcePort = u8_SourcePort;
		t_Message.u8_TargetPort = u8_TargetPort;
		t_Message.u8_Mode = u8_Mode;

		if (tp_Command == (const message_command *)0)
		{
			if (ui_Value < sizeof(task_comm_message))
				return FUNCTION_FAIL;

			t_Message.u8_Length = 0;
			ui_Value = sizeof(t_Message);

			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
			                        (const uint8 *)&t_Message,
			                        &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;
		}
		else
		{
			if ( ui_Value < sizeof(task_comm_message)+MESSAGE_COUNT_COMMAND_OFFSET+tp_Command->u8_Length )
				return FUNCTION_FAIL;

			t_Message.u8_Length = MESSAGE_COUNT_COMMAND_OFFSET + tp_Command->u8_Length;
			ui_Value = sizeof(t_Message);
			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
			                        (const uint8 *)&t_Message,
			                        &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;

			ui_Value = MESSAGE_COUNT_COMMAND_OFFSET;
			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
			                        (const uint8 *)tp_Command,
			                        &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;

			ui_Value = (uint)tp_Command->u8_Length;
			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
			                        tp_Command->u8p_Data,
			                        &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;
		}
	}
	else
	{
	    return TaskComm_SendCommand( u8_Address,
	                                 u8_SourcePort,
	                                 u8_TargetPort,
	                                 tp_Command,
	                                 u8_Mode );
	}

	return FUNCTION_OK;
}


uint TaskComm_Receive
( 
    uint8 u8_Address,
    uint8 *u8p_SourcePort,
    uint8 *u8p_TargetPort,
    message_command *tp_Command,
    uint8 *u8p_Mode 
)
{
	devcomm_int t_Device;
	devcomm_int t_Length;
	devcomm_int t_SourcePort;
	devcomm_int t_TargetPort;
	devcomm_int t_Mode;

	if (TaskComm_GetDevice((devcomm_int)u8_Address, &t_Device) != FUNCTION_OK)
		return FUNCTION_FAIL;

	if (REG_GET_BIT(m_ui_Flag[u8_Address], TASK_COMM_FLAG_SWITCH) == 0)
		return FUNCTION_FAIL;

	if ( DevComm_Receive( t_Device, (devcomm_int)u8_Address,
	                      &t_SourcePort,
	                      &t_TargetPort,
	                      m_u8_BufferCommand,
	                      &t_Length,
	                      &t_Mode ) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if (t_Length < MESSAGE_COUNT_COMMAND_OFFSET)
		return FUNCTION_FAIL;

	*u8p_SourcePort = (uint8)t_SourcePort;
	*u8p_TargetPort = (uint8)t_TargetPort;
	*u8p_Mode = (uint8)t_Mode;
	tp_Command->u8_Operation = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_OPERATION];
	tp_Command->u8_Parameter = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_PARAMETER];
	tp_Command->u8_Length = (uint8)t_Length - MESSAGE_COUNT_COMMAND_OFFSET;
	tp_Command->u8p_Data = &m_u8_BufferCommand[MESSAGE_COUNT_COMMAND_OFFSET];

	return FUNCTION_OK;
}

void TaskComm_ClearQueueMessage(void)
{
  	Lib_Memset(m_u8_BufferMessage[MESSAGE_ADDRESS_MASTER],0,TASK_COMM_BUFFER_SIZE_MESSAGE);
    Lib_Memset(m_u8_BufferMessage[MESSAGE_ADDRESS_SLAVE],0,TASK_COMM_BUFFER_SIZE_MESSAGE);
	LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_MASTER],
	                     (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_MASTER],
	                     TASK_COMM_BUFFER_SIZE_MESSAGE);
	LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_SLAVE],
	                     (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_SLAVE],
	                     TASK_COMM_BUFFER_SIZE_MESSAGE );
}

//Private function definition   私有函数定义
static uint TaskComm_InitializeBle(void)
{

    Ble_SetConfig(BLE_PARAM_CALLBACK_ON_WRITE,
                        (uint8 *)TaskComm_BleOnWrite,
                        sizeof(fp_on_write));
	Ble_SetConfig(BLE_PARAM_CALLBACK_ON_CONNECT,
						(uint8 *)TaskComm_BleOnConnect,
						sizeof(fp_on_connect));
    TaskComm_InitFrame(COMM_OPERATION_WRITE);
    TaskComm_InitFrame(COMM_OPERATION_READ);
    TaskComm_InitDeviceEvent();
    return FUNCTION_OK;
}

static uint TaskComm_InitializeComm(void)
{
	devcomm_profile t_Profile;
	devcomm_callback t_Callback;

	t_Profile.t_Address = MESSAGE_ADDRESS_MASTER;
	t_Profile.t_PacketLengthMax = TASK_COMM_PACKET_LENGTH_MAX;
	t_Profile.u16_Retry = TASK_COMM_SEND_RETRY;
	t_Profile.u16_Timeout = TASK_COMM_SEND_TIMEOUT;

	t_Callback.fp_HandleEvent = TaskComm_HandleEvent;
	t_Callback.fp_WriteDevice = TaskComm_WriteDevice;
	t_Callback.fp_ReadDevice = TaskComm_ReadDevice;
	t_Callback.fp_Memcpy = TaskComm_Memcpy;
	t_Callback.fp_GetCRC8 = TaskComm_GetCRC8;
	t_Callback.fp_GetCRC16 = TaskComm_GetCRC16;
	t_Callback.fp_EncryptionUpdate = TaskComm_EncryptionUpdate;
	t_Callback.fp_Encrypt = TaskComm_Encrypt;
	t_Callback.fp_Decrypt = TaskComm_Decrypt;
	t_Callback.fp_EnterCritical = (devcomm_callback_enter_critical)0;
	t_Callback.fp_ExitCritical = (devcomm_callback_exit_critical)0;
	if ( DevComm_Initialize(TASK_COMM_DEVICE_RF,
	                        &t_Profile,
	                        &t_Callback) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if ( DevComm_Link( TASK_COMM_DEVICE_RF,
	                   MESSAGE_ADDRESS_MASTER,
	                   TASK_COMM_PACKET_LENGTH_MASTER ) != FUNCTION_OK )
		return FUNCTION_FAIL;

	// if ( DevComm_Link( TASK_COMM_DEVICE_RF,
	//                    MESSAGE_ADDRESS_SLAVE,
	//                    TASK_COMM_PACKET_LENGTH_SLAVE ) != FUNCTION_OK )
	// 	return FUNCTION_FAIL;
	// LOG_INFO("02");

	if ( DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
	                               MESSAGE_ADDRESS_MASTER,
	                               DEVCOMM_ENCRYPTION_OFF ) != FUNCTION_OK )
	    return FUNCTION_FAIL;

	// if ( DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
	//                                MESSAGE_ADDRESS_SLAVE,
	//                                DEVCOMM_ENCRYPTION_OFF ) != FUNCTION_OK )
	//     return FUNCTION_FAIL;
	// REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_SLAVE], TASK_COMM_FLAG_SWITCH);
	REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_SWITCH);


	// LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_SLAVE],
	//                      (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_SLAVE],
	//                      TASK_COMM_BUFFER_SIZE_MESSAGE );

	LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_MASTER],
	                     (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_MASTER],
	                     TASK_COMM_BUFFER_SIZE_MESSAGE );
	return FUNCTION_OK;
}

static uint TaskComm_InitializeOS
( 
    devos_task_handle t_TaskHandle
)
{
    if (Task_ObtainMessageID(&m_ui_MessageID) != FUNCTION_OK)
        return FUNCTION_FAIL;

    if ( DevOS_MessageInitialize( (devos_int)m_ui_MessageID,
                                    (uint8 *)0,
                                    0 ) != FUNCTION_OK )
        return FUNCTION_FAIL;

    if ( DevOS_MessageRegister( (devos_int)m_ui_MessageID,
                                t_TaskHandle ) != FUNCTION_OK)
    {
        return FUNCTION_FAIL;
    }

	

	return FUNCTION_OK;

}
static void TaskComm_InitDeviceEvent(void)
{
    LibQueue_Initialize( &m_t_QueueDeviceEvent,
                         m_u8_BufferDeviceEvent,
                         TASK_COMM_BUFFER_SIZE_DEVICE_EVENT) ;
}
void TaskComm_InitFrame
( 
    uint ui_Operation
)
{
    comm_control * tp_Control;
    if(ui_Operation >= COMM_COUNT_OPERATION)
        return;
    tp_Control = &m_t_CommControl[ui_Operation]; 
    LibQueue_Initialize( &tp_Control->t_QueueData,
                                tp_Control->u8_BufferData,
                                m_u8_BufferSize[ui_Operation] );
    LibQueue_Initialize( &tp_Control->t_QueueLength,
                                tp_Control->u8_BufferLength,
                                sizeof(tp_Control->u8_BufferLength) );
}

static uint TaskComm_GetDevice
( 
    devcomm_int t_Address,
    devcomm_int *tp_Device 
)
{
    switch (t_Address){
    case MESSAGE_ADDRESS_MASTER:
        *tp_Device = TASK_COMM_DEVICE_RF;
        break;

    case MESSAGE_ADDRESS_SLAVE:
        *tp_Device = TASK_COMM_DEVICE_RF;
        break;

    default:
        return FUNCTION_FAIL;
    }

	if (REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) == 0)
		return FUNCTION_FAIL;

	return FUNCTION_OK;
}

static uint TaskComm_CheckCommandPending
( 
    devcomm_int t_Address 
)
{
	uint ui_Value;
	devcomm_int t_State;
	devcomm_int t_Device;
	devcomm_int t_CommandLength;
	task_comm_message t_Message;

	if ( TaskComm_GetDevice(t_Address, &t_Device) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if ( DevComm_Query(t_Device, t_Address, DEVCOMM_INFO_STATE, &t_State) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if ( t_State == DEVCOMM_STATE_BUSY )
		return FUNCTION_FAIL;

	ui_Value = sizeof(t_Message);
	if ( LibQueue_PopHead( &m_t_QueueMessage[t_Address],
	                       (uint8 *)&t_Message,
	                       &ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	if (ui_Value < sizeof(t_Message))
		return FUNCTION_FAIL;

	t_CommandLength = (devcomm_int)t_Message.u8_Length;
	ui_Value = (uint)t_CommandLength;
	if ( LibQueue_PopHead( &m_t_QueueMessage[t_Address],
	                       m_u8_BufferCommand,
	                       &ui_Value ) != FUNCTION_OK )
	    return FUNCTION_FAIL;

	if ( REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) == 0 )
		return FUNCTION_FAIL;

	return DevComm_Send( t_Device,
	                     t_Address,
	                     (devcomm_int)t_Message.u8_SourcePort,
	                     (devcomm_int)t_Message.u8_TargetPort,
	                     m_u8_BufferCommand,
	                     t_CommandLength,
	                     (devcomm_int)t_Message.u8_Mode );
}

static void TaskComm_Tick
( 
    uint16 u16_TickTime
)
{
	DevComm_Tick(TASK_COMM_DEVICE_RF, u16_TickTime);
}

static void TaskComm_HandleMessage(void)
{
	uint ui_Event;
	uint ui_Length;
	uint8 *u8p_MessageData;
	devos_int t_MessageLength;
	devcomm_int t_Address;
	devcomm_int t_Device;


	t_Address = MESSAGE_ADDRESS_MASTER;

	if (TaskComm_GetDevice(t_Address, &t_Device) != FUNCTION_OK)
		return;

	u8p_MessageData = DevOS_MessageReceive( (devos_int)m_ui_MessageID,
											&t_MessageLength );
	if (u8p_MessageData == (const uint8 *)0)
		return;

	ui_Length = sizeof(ui_Event);

	Task_EnterCritical();

	while ( LibQueue_PopHead( &m_t_QueueDeviceEvent,
								(uint8 *)&ui_Event,
								&ui_Length ) == FUNCTION_OK )
	{
		Task_ExitCritical();

		if (REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) != 0)
		{
			if  (ui_Event == TASK_COMM_EVENT_WRITE_DONE)
			{
				DevComm_WriteDeviceDone(t_Device);
			}
			else if (ui_Event == TASK_COMM_EVENT_READ_DONE)
			{
				DevComm_ReadDeviceDone( t_Device,
										m_u8p_ReadData,
										(devcomm_int)m_ui_ReadLength );
			}
		}

		Task_EnterCritical();
	}

	Task_ExitCritical();

	TaskComm_CheckCommandPending(t_Address);
	

	u8p_MessageData = DevOS_MessageReceive(TASK_MESSAGE_ID_TICK, &t_MessageLength);

	if (u8p_MessageData != (const uint8 *)0)
		TaskComm_Tick(*((uint16 *)u8p_MessageData));
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static uint TaskComm_CheckState
(
	uint8 *u8p_State
)
{
	uint ui_Event;
	uint ui_Length;
	devcomm_int t_Address;
	devcomm_int t_Device;
	devcomm_int t_State;


	*u8p_State = 0;

	t_Device = MESSAGE_ADDRESS_MASTER;

	if (TaskComm_GetDevice(t_Address, &t_Device) == FUNCTION_OK)
	{
		if (DevComm_Query(t_Device, t_Address, DEVCOMM_INFO_STATE, 
			&t_State) != FUNCTION_OK)
		{
			return FUNCTION_FAIL;
		}

		if (t_State == DEVCOMM_STATE_BUSY) 
		{
			*u8p_State = 1;
		}

		ui_Length = sizeof(ui_Event);

		if (LibQueue_PeekHead(&m_t_QueueDeviceEvent, 
			(uint8 *)&ui_Event, &ui_Length) == FUNCTION_OK)
		{
			*u8p_State = 1;
		}
	}
	
	return FUNCTION_OK;
}



static uint TaskComm_HandleEvent
( 
    devcomm_int t_Device,
    devcomm_int t_Address,
    devcomm_int t_SourcePort,
    devcomm_int t_TargetPort,
    devcomm_int t_Event
)
{
	uint ui_Value;
	uint ui_Acknowledge;
	uint8 u8_Port;
	devcomm_int t_Length;
	devcomm_int t_Mode;
	message_command t_Command;
	LOG_INFO("TaskComm_HandleEvent");
	if (TaskComm_GetDevice(t_Address, &t_Device) != FUNCTION_OK)
		return FUNCTION_FAIL;

	if (REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) == 0)
		return FUNCTION_FAIL;

	switch (t_Event) {
	case MESSAGE_EVENT_TIMEOUT:
		Task_SendMessage(m_ui_MessageID, (const uint8 *)0, 0);
	    return FUNCTION_OK;

	case MESSAGE_EVENT_RECEIVE_DONE:
	    LOG_INFO("TaskComm_HandleEvent:MESSAGE_EVENT_RECEIVE_DONE");
	    t_Length = sizeof(m_u8_BufferCommand);
	    if ( DevComm_Receive( t_Device,
	                          t_Address,
	                          &t_SourcePort,
	                          &t_TargetPort,
	                          m_u8_BufferCommand,
	                          &t_Length,
	                          &t_Mode ) != FUNCTION_OK )
	        return FUNCTION_FAIL;
	    if (t_Length < MESSAGE_COUNT_COMMAND_OFFSET)
	        return FUNCTION_FAIL;

	    t_Command.u8_Operation = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_OPERATION];
	    t_Command.u8_Parameter = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_PARAMETER];
	    t_Command.u8_Length = (uint8)t_Length - MESSAGE_COUNT_COMMAND_OFFSET;
	    t_Command.u8p_Data = m_u8_BufferCommand + MESSAGE_COUNT_COMMAND_OFFSET;
	    LOG_INFO("cmd operation:%d",t_Command.u8_Operation);
	    switch (t_Command.u8_Operation) {
	    case MESSAGE_OPERATION_SET:
#if TASK_COMM_SET_AUTHORITY
	        if ( REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_PRIMARY) == 0 )
	            return FUNCTION_FAIL;
#endif
	    case MESSAGE_OPERATION_GET:
	        if ( REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_BONDED) == 0 )
	            return FUNCTION_FAIL;
	        break;
	    default:
	        break;
	    }

	    u8_Port = MESSAGE_GET_MAJOR_PORT((uint8)t_TargetPort);
	    switch (u8_Port) {
	    case MESSAGE_PORT_TASK:
	        ui_Acknowledge = Task_HandleCommand( (uint8)t_SourcePort,
	                                                  (uint8)t_TargetPort,
	                                                  &t_Command );
	        break;

	    default:
	        ui_Acknowledge = FUNCTION_FAIL;
	        break;
	    }

	    if (ui_Acknowledge == FUNCTION_OK)
	    {
	        switch (t_Command.u8_Operation){
	        case MESSAGE_OPERATION_NOTIFY:
	        case MESSAGE_OPERATION_ACKNOWLEDGE:
	        case MESSAGE_OPERATION_PAIR:
	        case MESSAGE_OPERATION_UNPAIR:
	        case MESSAGE_OPERATION_BOND:
	            return TaskComm_Send( (uint8)t_Address,
	                                  (uint8)t_TargetPort,
	                                  (uint8)t_SourcePort,
	                                  &t_Command,
	                                  MESSAGE_MODE_ACKNOWLEDGEMENT );

	        default:
	            if ( LibQueue_GetConfig( &m_t_QueueMessage[t_Address],
	                                     LIB_QUEUE_PARAM_BUFFER_SPACE,
	                                     (void *)&ui_Value ) == FUNCTION_OK )
	            {
	                if ( ui_Value >= m_u8_BufferMessageLength[t_Address] &&
	                     t_Command.u8_Operation == MESSAGE_OPERATION_EVENT &&
	                     t_Mode == MESSAGE_MODE_ACKNOWLEDGEMENT              )
	                {
	                    return TaskComm_Send( (uint8)t_Address,
	                                          (uint8)t_TargetPort,
	                                          (uint8)t_SourcePort,
	                                          &t_Command,
	                                          MESSAGE_MODE_NO_ACKNOWLEDGEMENT );
	                }
	            }
	        }
	    }

	    return ui_Acknowledge;

    default:
        return FUNCTION_FAIL;
	}
}


static uint TaskComm_WriteDevice
( 
    devcomm_int t_Device,
    const uint8 *u8p_Data,
    devcomm_int t_Length 
)
{
	LOG_INFO("TaskComm_WriteDevice");
    switch (t_Device) 
    {

        case TASK_COMM_DEVICE_RF:
            return TaskComm_Write(u8p_Data,
                                (uint)t_Length );

        default:
            return FUNCTION_FAIL;
    }
	return FUNCTION_OK;
}


static uint TaskComm_Write
( 
    const uint8 *u8p_Data,
    uint ui_Length 
)
{
	LOG_INFO("TaskComm_Write");
    comm_control *tp_Control = &m_t_CommControl[COMM_OPERATION_WRITE]; 
	uint ui_Value;
	if (u8p_Data != (const uint8 *)0)
	{
	    LibQueue_GetConfig( &tp_Control->t_QueueLength,
            LIB_QUEUE_PARAM_BUFFER_SPACE,(void *)&ui_Value ) ;
			

	    if ( TaskComm_AddFrame( COMM_OPERATION_WRITE,
	                            u8p_Data,
	                            ui_Length ) != FUNCTION_OK )
        {
            TaskComm_HandleDeviceRfEvent(TASK_COMM_EVENT_WRITE_DONE,(const uint8 *)0, 0 );
            return FUNCTION_FAIL;
        }
	        

		if (ui_Value >= sizeof(tp_Control->u8_BufferLength))
		{
		    return TaskComm_ProcessFrame(COMM_OPERATION_WRITE,
		                                u8p_Data,
		                                ui_Length );
		}

		return FUNCTION_OK;
	}
	else
	{
		ui_Length = sizeof(ui_Value);
		if ( LibQueue_PeekHead( &tp_Control->t_QueueLength,
		                        (uint8 *)&ui_Value,
		                        &ui_Length ) != FUNCTION_OK )
			return FUNCTION_FAIL;
		ui_Length = ui_Value;

		if ( LibQueue_GetConfig( &tp_Control->t_QueueData,
		                         LIB_QUEUE_PARAM_HEAD,
		                         (void *)&ui_Value ) != FUNCTION_OK )
			return FUNCTION_FAIL;

		return TaskComm_ProcessFrame( COMM_OPERATION_WRITE,
		                            tp_Control->u8_BufferData + ui_Value,
		                            ui_Length );
	}
}


static uint TaskComm_ReadDevice
( 
    devcomm_int t_Device,
    uint8 *u8p_Data,
    devcomm_int *tp_Length 
)
{
	uint ui_Length = (uint)(*tp_Length);;
	uint ui_Return;

	switch (t_Device) 
    {
        case TASK_COMM_DEVICE_RF:
            ui_Return = TaskComm_Read( u8p_Data,
                                        &ui_Length );
            break;

        default:
            ui_Return = FUNCTION_FAIL;
            break;
	}

	*tp_Length = (devcomm_int)ui_Length;

	return ui_Return;
}

static uint TaskComm_Read
(
    uint8 *u8p_Data,
    uint *uip_Length 
)
{
    uint ui_Value;
    uint ui_Length = sizeof(ui_Value);
	if ( TaskComm_PopFrame(COMM_OPERATION_READ,
	                        u8p_Data,
	                        uip_Length ) != FUNCTION_OK )
		return FUNCTION_FAIL;

    comm_control *tp_Control = &m_t_CommControl[COMM_OPERATION_READ]; 


    if ( LibQueue_PeekHead( &tp_Control->t_QueueLength,
                            (uint8 *)&ui_Value,
                            &ui_Length ) != FUNCTION_OK )
		return FUNCTION_OK;

	ui_Length = ui_Value;
	if ( LibQueue_GetConfig( &tp_Control->t_QueueData,
	                         LIB_QUEUE_PARAM_HEAD,
	                         (void *)&ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;

	return TaskComm_ProcessFrame(COMM_OPERATION_READ,
	                            tp_Control->u8_BufferData + ui_Value,
	                            ui_Length );
}
static void TaskComm_Memcpy
( 
    uint8 *u8p_Target, 
    const uint8 *u8p_Source, 
    devcomm_int t_Length 
)
{
    Lib_Memcpy(u8p_Target, u8p_Source, (uint)t_Length);
}


static uint8 TaskComm_GetCRC8
( 
    const uint8 *u8p_Data, 
    devcomm_int t_Length, 
    uint8 u8_Base 
)
{
	return LibChecksum_GetChecksumPartial8Bit(u8p_Data, (uint16)t_Length, u8_Base);
}


static uint16 TaskComm_GetCRC16
( 
    const uint8 *u8p_Data, 
    devcomm_int t_Length, 
    uint16 u16_Base 
)
{
	return LibChecksum_GetChecksumPartial16Bit(u8p_Data, (uint16)t_Length, u16_Base);
}

static void TaskComm_EncryptionUpdate(void)
{
    AES_SetKey(0, m_u8_TempIv);
}

static void TaskComm_Encrypt
( 
    uint8 *u8p_Data, 
    devcomm_int t_Length 
)
{
    AES_CFB_encrypt((uint8_t *)u8p_Data, t_Length);
}

static void TaskComm_Decrypt
( 
    uint8 *u8p_Data, 
    devcomm_int t_Length 
)
{
    AES_CFB_decrypt((uint8_t *)u8p_Data, t_Length);
}


static uint TaskComm_SavePairingInfo(void)
{
    return FUNCTION_OK;
}

static uint TaskComm_SendCommand
( 
    uint8 u8_Address,
    uint8 u8_SourcePort,
    uint8 u8_TargetPort,
    const message_command *tp_Command,
    uint8 u8_Mode 
)
{
	devcomm_int t_Device;
	devcomm_int t_CommandLength;
	LOG_INFO("TaskComm_SendCommand");
	if ( TaskComm_GetDevice((devcomm_int)u8_Address, &t_Device) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if ( REG_GET_BIT(m_ui_Flag[u8_Address], TASK_COMM_FLAG_SWITCH) == 0 )
		return FUNCTION_FAIL;

	uint8 *u8p_Command;
	u8p_Command = (uint8 *)0;
	t_CommandLength = 0;

	if (tp_Command != (const message_command *)0)
	{
	    t_CommandLength = tp_Command->u8_Length + MESSAGE_COUNT_COMMAND_OFFSET;
		m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_OPERATION] = tp_Command->u8_Operation;
		m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_PARAMETER] = tp_Command->u8_Parameter;
		Lib_Memcpy( m_u8_BufferCommand + MESSAGE_COUNT_COMMAND_OFFSET,
		            tp_Command->u8p_Data,
		            (uint)tp_Command->u8_Length );
		u8p_Command = m_u8_BufferCommand;
	}
	return DevComm_Send( t_Device,
	                     (devcomm_int)u8_Address,
	                     (devcomm_int)u8_SourcePort,
	                     (devcomm_int)u8_TargetPort,
	                     u8p_Command,
	                     t_CommandLength,
	                     (devcomm_int)u8_Mode );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void TaskComm_BleOnConnect(void)
{
	m_u8_UpdateKeyFlag =1;
}

static void TaskComm_BleOnWrite
(
    uint16 u16_ConnetHandle, 
    uint16 u16_AttIndex, 
    uint8 *u8p_Data, 
    uint16 u16_Len
)
{
    (void)u16_ConnetHandle;

    switch (u16_AttIndex)
    {
        case COMMUNICATION_INDEX:
        {
            TaskComm_CommunicationServicOnWrite(u8p_Data,u16_Len);
        }
            break;
        case MANAGEMENT_INDEX:
        {
            TaskComm_ManagementServicOnWrite(u8p_Data,u16_Len);

        }
            break;
        default:
            return;
    }
}
static void TaskComm_CommunicationServicOnWrite
(
    uint8 * u8p_Data, 
    uint16 u16_Length
)
{
    static uint8 u8_Count = 0;
    static uint16 u16_BufferPointer = 0;
    uint8 u8_Index;
    uint8 u8_Finish;

    u8_Index = (u8p_Data[u16_Length-1] & 0xF0) >> 4;
    u8_Finish = u8p_Data[u16_Length-1] & 0x0F;

    if (u8_Count != u8_Index || u16_BufferPointer + u16_Length-1 > RECEIVE_BUFFER_SIZE)
    {
        u16_BufferPointer = 0;
        u8_Count = u8_Index;
    }
    Lib_Memcpy(m_u8_ReceiveBuff+u16_BufferPointer, u8p_Data, u16_Length-1);
    u16_BufferPointer += u16_Length-1;
    if (u8_Finish != 0)
    {
        TaskComm_CommandReceived(m_u8_ReceiveBuff,u16_BufferPointer);
        u16_BufferPointer = 0;
    }
            
}

static void TaskComm_ManagementServicOnWrite
(
    uint8 * u8p_Data, 
    uint16 u16_Length
)
{
    if ( Lib_Memcmp(u8p_Data, m_u8_Reboot, sizeof(m_u8_Reboot)) == FUNCTION_OK )
    {
		LOG_INFO("soft Reset!!!");
        //Drv_SoftRest(); 
    }
    if ( Lib_Memcmp(u8p_Data, m_u8_RebootAsc, sizeof(m_u8_RebootAsc)) == FUNCTION_OK )
    {
        LOG_INFO("Gc Reset!!!");
		// Gc_Reset();
    }
    if ( Lib_Memcmp(u8p_Data, m_u8_GetR, sizeof(m_u8_GetR)) == FUNCTION_OK )//cmd  Get R
    { 
		LOG_INFO("Get R");
        // TaskClucose_GetRParam(u8_Data, &u32_Length);
        // TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,u8_Data,u32_Length);
    }
    if ( Lib_Memcmp(u8p_Data, m_u8_CalR, sizeof(m_u8_CalR)) == FUNCTION_OK )//cmd Cal R
    {
		LOG_INFO("Cal R");
        // TaskClucose_SetCalibrateRFlag();
    }
    if ( Lib_Memcmp(u8p_Data, m_u8_GetPairInfo1, sizeof(m_u8_GetPairInfo1)) == FUNCTION_OK )
    {
		LOG_INFO("Get Pair Info 0");
        // Lib_Memset(u8_Data,0,sizeof(u8_Data));
        // Lib_Memcpy(u8_Data,m_t_PairingInfo[0].u8_PairingID,14);
        // Lib_Memcpy(u8_Data+14,m_t_PairingInfo[0].u8_BondID,6);
        // TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,u8_Data,20);
    }
    if ( Lib_Memcmp(u8p_Data, m_u8_GetPairInfo2, sizeof(m_u8_GetPairInfo2)) == FUNCTION_OK )
    {
		LOG_INFO("Get Pair Info 1");
        // Lib_Memset(u8_Data,0,sizeof(u8_Data));
        // Lib_Memcpy(u8_Data,m_t_PairingInfo[1].u8_PairingID,14);
        // Lib_Memcpy(u8_Data+14,m_t_PairingInfo[1].u8_BondID,6);
        // TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,u8_Data,20);
    }

    if ( Lib_Memcmp(u8p_Data, m_u8_Log, sizeof(m_u8_Log)) == FUNCTION_OK )
    {
		LOG_INFO("Get Log");
        // uint16 * u16p_Index = (uint16 *)(&u8p_Data[3]);
        //     #if CGMS_LOG_SW
        // t_log t_Log;
        
        // if(TaskMonitor_LoadLog( *u16p_Index,&t_Log ))
        // {
        //         TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,(uint8 *)&t_Log,sizeof(t_Log));
        // }
        // else
        // {
            
        // }
        
        // #endif
    }
    if ( Lib_Memcmp(u8p_Data, m_u8_GetLogNum, sizeof(m_u8_GetLogNum)) == FUNCTION_OK )
    {
			LOG_INFO("Get Log Num");
        // #if CGMS_LOG_SW
        // uint16 u16_LogHeaderIndex = TaskMonitor_GetLogHeadIndex();
        // TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,(uint8 *)&u16_LogHeaderIndex,(uint8_t) sizeof(u16_LogHeaderIndex));
        // #endif
    }
    if ( Lib_Memcmp(u8p_Data, m_u8_ClearPairingInfo, sizeof(m_u8_ClearPairingInfo)) == FUNCTION_OK )
    {
		LOG_INFO("Clear pair info ");
        // app_sched_event_put(0,0, TaskComm_HandlerClearPairInfo);

    }

}

static void TaskComm_CommandReceived
(
    uint8 * u8p_Data, 
    uint16 u16_Length
)
{
  LOG_INFO("TaskComm_CommandReceived");
  comm_control * tp_Control = &m_t_CommControl[COMM_OPERATION_READ];
	uint ui_Value;
	LibQueue_GetConfig( &tp_Control->t_QueueLength,
	                    LIB_QUEUE_PARAM_BUFFER_SPACE,
	                    (void *)&ui_Value );

	if( TaskComm_AddFrame(COMM_OPERATION_READ,
	                      u8p_Data,
	                      u16_Length ) != FUNCTION_OK )
	    return;

	if (ui_Value >= sizeof(tp_Control->u8_BufferLength))//if first frame ,start process Frame 
	{
		Lib_Memcpy( m_u8_ReceiveBuffBak,u8p_Data,u16_Length );

		TaskComm_ProcessFrame(COMM_OPERATION_READ,
	                         m_u8_ReceiveBuffBak,
	                         u16_Length );
	}
}


void TaskComm_ResetFrame
( 
    uint ui_Operation
)
{
    comm_control * tp_Control;
    if(ui_Operation >= COMM_COUNT_OPERATION)
        return;
	uint ui_Value = 1;
    tp_Control = &m_t_CommControl[ui_Operation]; 
	LibQueue_SetConfig( &tp_Control->t_QueueLength,
	                    LIB_QUEUE_PARAM_BUFFER_CLEAR,
	                    (void *)&ui_Value );
	LibQueue_SetConfig( &tp_Control->t_QueueData,
	                    LIB_QUEUE_PARAM_BUFFER_CLEAR,
	                    (void *)&ui_Value );
}

static uint TaskComm_AddFrame
( 
    uint ui_Operation,
    const uint8 *u8p_Data,
    uint ui_Length 
)
{
    comm_control * tp_Control;
    uint ui_Value;
    if (ui_Length == 0)
        return FUNCTION_FAIL;
    if(ui_Operation >= COMM_COUNT_OPERATION)
        return FUNCTION_FAIL;
    tp_Control = &m_t_CommControl[ui_Operation]; 

	if ( LibQueue_GetConfig( &tp_Control->t_QueueData,
	                         LIB_QUEUE_PARAM_BUFFER_SPACE,
	                         (void *)&ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;

    if ( ui_Length > ui_Value )
    {
        TaskComm_ResetFrame(ui_Operation);
        return FUNCTION_FAIL;
    }

    ui_Value = sizeof(ui_Length);
    if ( LibQueue_PushTail( &tp_Control->t_QueueLength,
                            (const uint8 *)&ui_Length,
                            &ui_Value ) != FUNCTION_OK )

    {
        TaskComm_ResetFrame(ui_Operation);
        return FUNCTION_FAIL;
    }

    if ( LibQueue_PushTail( &tp_Control->t_QueueData,
                            u8p_Data,
                            &ui_Length ) != FUNCTION_OK )
    {
        TaskComm_ResetFrame(ui_Operation);
        return FUNCTION_FAIL;
    }
    return FUNCTION_OK;
}


static uint TaskComm_PopFrame//TaskComm_RemoveFrame
( 
    uint ui_Operation,
    uint8 *u8p_Data,
    uint *uip_Length
)
{
    comm_control * tp_Control;
    uint ui_Value;
	uint ui_Length = sizeof(ui_Value);

    if (uip_Length == (uint *)0)
        return FUNCTION_FAIL;
    tp_Control = &m_t_CommControl[ui_Operation]; 

	//Check if there is any frame can be read
	if ( LibQueue_PopHead( &tp_Control->t_QueueLength,
	                       (uint8 *)&ui_Value,
	                       &ui_Length ) != FUNCTION_OK )
    {
        TaskComm_ResetFrame(ui_Operation);
        return FUNCTION_FAIL;
    }

	if (*uip_Length > ui_Value)
		*uip_Length = ui_Value;
	if ( LibQueue_PopHead( &tp_Control->t_QueueData,
	                       u8p_Data,
	                       uip_Length ) != FUNCTION_OK )
    {
        TaskComm_ResetFrame(ui_Operation);
        return FUNCTION_FAIL;
    }

	if ( LibQueue_GetConfig( &tp_Control->t_QueueLength,
	                         LIB_QUEUE_PARAM_BUFFER_SPACE,
	                         (void *)&ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;

	if ( ui_Value >= sizeof(tp_Control->u8_BufferLength) )
		TaskComm_ResetFrame(ui_Operation);

	return FUNCTION_OK;
}


static uint TaskComm_ProcessFrame
( 
    uint ui_Operation,
    const uint8 *u8p_Data,
    uint ui_Length 
)
{
	LOG_INFO("TaskComm_ProcessFrame");
	uint8 u8_Value = 0;
	uint16 u16_Interval;
    switch (ui_Operation)
    {
    case COMM_OPERATION_WRITE:
        if(Ble_GetConfig(BLE_PARAM_CONNECT_STATE,&u8_Value,0) != FUNCTION_OK)
			return FUNCTION_FAIL;
		if(u8_Value == 0)
			return FUNCTION_FAIL;

		Ble_GetConfig(BLE_PARAM_CONNECT_INTERVAL,(uint8 *)&m_u16_ConnectInterval,0); 
			

		
		u16_Interval = m_u16_ConnectInterval * m_u16_ConnectWriteDelayRatio;
		// u16_Interval = u16_Interval * 1250 /1000;

		TaskComm_StartWriteTimer(u16_Interval);

		// TaskRF_StartTimerWrite(APP_TIMER_TICKS(u16_Interval));

		TaskComm_Notify(COMMUNICATION_INDEX,u8p_Data,ui_Length);

        break;
    case COMM_OPERATION_READ:
        LOG_INFO("TaskComm_ProcessFrame:COMM_OPERATION_READ");
        TaskComm_HandleDeviceRfEvent( TASK_COMM_EVENT_READ_DONE,
                                u8p_Data,
                                ui_Length);
        break;    
    default:
        return FUNCTION_FAIL;
        break;
    }


	return FUNCTION_OK;
}

static uint TaskComm_Notify
(    
	uint16 u16_AttHandle,  
    const uint8 *u8p_Data, 
    uint ui_Len
)
{
	static uint8 u8_count = 0;
	static uint16 u16_length = 0;
	static uint8 u8_Finished = 0;
	static uint8 u8_SendBuff[BLE_MTU -3];
    static uint  temp_code =0;
	if(u16_AttHandle != COMMUNICATION_INDEX)
		return FUNCTION_FAIL;

	u8_count++;
    u16_length = 0;
    u8_Finished = 0;
	while(ui_Len > 0)
	{
		if(ui_Len > BLE_MTU -4)
		{
			u16_length = BLE_MTU -4;
			ui_Len -= BLE_MTU -4;
            u8_Finished = 0;
		}
		else
		{
			u16_length = ui_Len;
            ui_Len = 0;
			u8_Finished = 1;
		}
        Lib_Memset(u8_SendBuff,0,sizeof(u8_SendBuff));
 		Lib_Memcpy( u8_SendBuff,u8p_Data,(uint) u16_length );
		u8p_Data += u16_length;
		u8_SendBuff[u16_length] =((u8_count<<4)& 0xF0) |(u8_Finished & 0x0F);
        u16_length++;

		Ble_AttributeNotify(COMMUNICATION_INDEX,u8_SendBuff,u16_length);

	}

	return FUNCTION_OK;
}





static void TaskComm_StartWriteTimer
(
	uint16 u16_Interval
)
{
	LOG_INFO("TaskComm_StartWriteTimer");
	uint32 u32_Period = u16_Interval;
    bool b_Repeat = false;
    uint8 u8_Value = 1; 

    DrvTimer_SetConfig(DRV_TIMER_ID2,DRV_TIMER_PARAM_PERIOD,
                    (uint8 *)&u32_Period,
                    sizeof(u32_Period));           
    DrvTimer_SetConfig(DRV_TIMER_ID2,DRV_TIMER_PARAM_REPEAT,
                    (uint8 *)&b_Repeat,
                    sizeof(b_Repeat));
    DrvTimer_SetConfig(DRV_TIMER_ID2,DRV_TIMER_PARAM_CALLBACK,
                    (uint8 *)TaskComm_WrtieTimerCallback,
                    sizeof(fp_timer_callback));   
    DrvTimer_SetConfig(DRV_TIMER_ID2,DRV_TIMER_PARAM_SWITCH,
                    (uint8 *)&u8_Value,
                    sizeof(u8_Value));  
}


static void TaskComm_WrtieTimerCallback(void)
{
	TaskComm_WriteDone( );
}

static void TaskComm_WriteDone( void )
{
	comm_control *tp_Control = &m_t_CommControl[COMM_OPERATION_WRITE]; 
    uint ui_Value;
    uint ui_Length = m_u8_BufferSize[DATA_WRITE_BUFFER_SIZE];

	TaskComm_PopFrame(COMM_OPERATION_WRITE,
	                         (uint8 *)0,&ui_Length );

    LibQueue_GetConfig( &tp_Control->t_QueueLength,
            LIB_QUEUE_PARAM_BUFFER_SPACE,(void *)&ui_Value ) ;
    
    if (ui_Value >= sizeof(tp_Control->u8_BufferLength))
    {
    
		TaskComm_HandleDeviceRfEvent(TASK_COMM_EVENT_WRITE_DONE,
                                            (const uint8 *)0, 0 );
    }
    else
    {
	    TaskComm_Write((const uint8 *)0, 0 );
    }


}


static uint TaskComm_HandleDeviceRfEvent
( 
    uint ui_Event,
    const uint8 *u8p_Data,
    uint ui_Length 
)
{
	uint ui_Value;
    ui_Value = sizeof(ui_Event);
    if ( LibQueue_PushTail( &m_t_QueueDeviceEvent,
                            (const uint8 *)&ui_Event,
                            &ui_Value ) == FUNCTION_OK )
    {
        if (ui_Event == TASK_COMM_EVENT_READ_DONE)
        {
            m_u8p_ReadData = u8p_Data;
            m_ui_ReadLength = ui_Length;
        }
    }
	Task_SendMessage(m_ui_MessageID, (const uint8 *)0, 0);
	return FUNCTION_OK;
}
static void TaskComm_UpdateBroadcast(void)
{
	uint8 i;
	m_t_Broadcast.u8_RFSignal = 0;
	for (uint8 i=0; i<TASK_COMM_COUNT_IDENTIFIER; i++)
    {
        if (m_t_PairingInfo[i].u8_Role == ROLE_PRIMARY)
            REG_SET_BIT(m_t_Broadcast.u8_RFSignal, i);
    }
	for(i=TASK_COMM_BROADCAST_DATA_SIZE-6;i<TASK_COMM_BROADCAST_DATA_SIZE;i++)//Reserved broadcast packet last 6 byte
	{
		m_t_Broadcast.u8_Data[i] = 0xFF;
	}
	
	m_t_Broadcast.u8_Checksum = 
	LibChecksum_GetChecksum8Bit( (const uint8 *)&m_t_Broadcast,
		                             sizeof(m_t_Broadcast) - sizeof(m_t_Broadcast.u8_Checksum) );
	Ble_UpdateAdvData((uint8 *)&m_t_Broadcast,sizeof(m_t_Broadcast));
	LOG_INFO("TaskComm_UpdateBroadcast");

}
